using dotnet_ef_admin.Src.Common.Const;
using dotnet_ef_admin.Src.Models;
using dotnet_ef_admin.Src.Utilities;
using Microsoft.EntityFrameworkCore;

namespace dotnet_ef_admin.Src.Services;

/// <summary>
/// 菜单服务类，实现了IMenuService接口。
/// </summary>
public class MenuService(DbCtx _context) : IMenuService {
    /// <summary>
    /// 异步获取所有菜单。
    /// </summary>
    /// <returns>返回一个包含所有菜单的集合。</returns>
    public async Task<IEnumerable<MenuNode>> GetAllMenusAsync(FindAllDictTypesDto dto) {
        var menus = await _context.Menus
        .Where(m => string.IsNullOrEmpty(dto.Keywords) || m.Name.Contains(dto.Keywords))
        .Select(m => new MenuNodeResult {
            Id = m.Id,
            Name = m.Name,
            ParentId = m.ParentId,
            Sort = m.Sort,
            // Type = m.Type,
            RouteName = m.RouteName,
            RoutePath = m.RoutePath,
            Component = m.Component,
            Perm = m.Perm,
            Visible = m.Visible,
            Icon = m.Icon
        }).ToListAsync();
        return menus;
    }

    /// <summary>
    /// 异步根据ID获取菜单。
    /// </summary>
    /// <param name="id">菜单ID。</param>
    /// <returns>返回与ID匹配的菜单，如果没有找到则返回null。</returns>
    public async Task<MenuNodeResult?> GetMenuByIdAsync(int id) {
        var existingMenu = await _context.Menus.FindAsync(id);

        if (existingMenu == null) throw new Exception("菜单不存在");

        return new MenuNodeResult {
            Id = existingMenu.Id,
            Name = existingMenu.Name,
            ParentId = existingMenu.ParentId,
            Sort = existingMenu.Sort,
            Type = EnumHelper.ToStringUpper(existingMenu.Type),
            RouteName = existingMenu.RouteName,
            RoutePath = existingMenu.RoutePath,
            Component = existingMenu.Component,
            Perm = existingMenu.Perm,
            Visible = existingMenu.Visible,
            Icon = existingMenu.Icon
        };
    }

    /// <summary>
    /// 异步创建新菜单。
    /// </summary>
    /// <param name="menu">要创建的菜单对象。</param>
    /// <returns>返回创建的菜单。</returns>
    public async Task<MenuNodeResult> CreateMenuAsync(MneuNodeRequest menu) {
        var newMenu = new Menu {
            ParentId = menu.ParentId,
            Name = menu.Name,
            Sort = menu.Sort,
            Type = EnumHelper.ParseEnum<MenuTypeEnum>(menu.Type),
            RouteName = menu.RouteName,
            RoutePath = menu.RoutePath,
            Component = menu.Component,
            Perm = menu.Perm,
            Visible = menu.Visible,
            Icon = menu.Icon,
            KeepAlive = menu.KeepAlive
        };
        _context.Menus.Add(newMenu);
        await _context.SaveChangesAsync();
        return new MenuNodeResult {
            Id = newMenu.Id,
            Name = newMenu.Name,
            ParentId = newMenu.ParentId,
            Sort = newMenu.Sort,
            Type = EnumHelper.ToStringUpper(newMenu.Type),
            RouteName = newMenu.RouteName,
            RoutePath = newMenu.RoutePath,
            Component = newMenu.Component,
            Perm = newMenu.Perm,
            Visible = newMenu.Visible,
            Icon = newMenu.Icon
        };
    }

    /// <summary>
    /// 异步更新现有菜单。
    /// </summary>
    /// <param name="menu">要更新的菜单对象。</param>
    /// <returns>返回更新后的菜单。</returns>
    public async Task<MenuNodeResult> UpdateMenuAsync(MenuNodeResult menu) {
        var existingMenu = await _context.Menus.FindAsync(menu.Id);
        if (existingMenu == null) {
            throw new Exception("菜单不存在");
        }
        var newMenu = new Menu {
            Id = menu.Id,
            ParentId = menu.ParentId,
            Name = menu.Name,
            Sort = menu.Sort,
            Type = EnumHelper.ParseEnum<MenuTypeEnum>(menu.Type),
            RouteName = menu.RouteName,
            RoutePath = menu.RoutePath,
            Component = menu.Component,
            Perm = menu.Perm,
            Visible = menu.Visible,
            Icon = menu.Icon,
            KeepAlive = menu.KeepAlive
        };
        _context.Entry(existingMenu).CurrentValues.SetValues(newMenu);

        await _context.SaveChangesAsync();
        return menu;
    }

    /// <summary>
    /// 异步删除菜单。
    /// </summary>
    /// <param name="id">要删除的菜单ID。</param>
    public async Task DeleteMenuAsync(int id) {
        var menu = await _context.Menus.FindAsync(id);
        if (menu != null) {
            _context.Menus.Remove(menu);
            await _context.SaveChangesAsync();
        }
        throw new Exception("菜单不存在");
    }

    public async Task<List<MenuRoute>> GetListRoutes() {
        var menuList = await _context.Menus.ToListAsync();

        return BuildRoutes(RootConstants.RootNodeId, menuList);
    }

    private static List<MenuRoute> BuildRoutes(int parentId, List<Menu> menuList) {

        return menuList
        .Where(item => item.ParentId == parentId && item.Type != MenuTypeEnum.ButtonPermission)
        .Select(item => {
            var children = BuildRoutes(item.Id, menuList);

            var meta = new MenuMeta {
                Title = item.Name,
                Icon = item.Icon,
                Hidden = item.Visible == StatusConstants.Disable,
                AlwaysShow = children.Count > 0,
                KeepAlive = item.KeepAlive == 1
            };

            return new MenuRoute {
                Name = item.RouteName,
                Path = item.RoutePath,
                Component = item.Component,
                Meta = meta,
                Children = children
            };
        }).ToList();
    }
}
